6600 // Console input and output.
6601 // Input is from the keyboard or serial port.
6602 // Output is written to the screen and serial port.
6603 
6604 #include "types.h"
6605 #include "defs.h"
6606 #include "param.h"
6607 #include "traps.h"
6608 #include "spinlock.h"
6609 #include "fs.h"
6610 #include "file.h"
6611 #include "mmu.h"
6612 #include "proc.h"
6613 #include "x86.h"
6614 
6615 #define HISTORY_SIZE 16
6616 #define INPUT_BUF 128
6617 
6618 static void consputc(int);
6619 
6620 static int panicked = 0;
6621  static char commands[HISTORY_SIZE][INPUT_BUF];
6622  static int numOfComm = 0;
6623  static int arrowMarker = 0; //this marker will tell us which command from the
6624 //history to show right now
6625  static int historyMarker = 0; //this marker will tel us where in the commands
6626 //array to put the new command
6627  static int flag = 0; //this flag will stay 0 until we will have 16 commands
6628 // static int len = 0;
6629 
6630 
6631 
6632 static struct {
6633   struct spinlock lock;
6634   int locking;
6635 } cons;
6636 
6637 static void
6638 printint(int xx, int base, int sgn)
6639 {
6640   static char digits[] = "0123456789abcdef";
6641   char buf[16];
6642   int i = 0, neg = 0;
6643   uint x;
6644 
6645   if(sgn && xx < 0){
6646     neg = 1;
6647     x = -xx;
6648   } else
6649     x = xx;
6650   do{
6651     buf[i++] = digits[x % base];
6652   }while((x /= base) != 0);
6653   if(neg)
6654     buf[i++] = '-';
6655 
6656   while(--i >= 0)
6657     consputc(buf[i]);
6658 }
6659 
6660 // Print to the console. only understands %d, %x, %p, %s.
6661 void
6662 cprintf(char *fmt, ...)
6663 {
6664   int i, c, state, locking;
6665   uint *argp;
6666   char *s;
6667 
6668   locking = cons.locking;
6669   if(locking)
6670     acquire(&cons.lock);
6671 
6672   argp = (uint*)(void*)(&fmt + 1);
6673   state = 0;
6674   for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
6675     if(c != '%'){
6676       consputc(c);
6677       continue;
6678     }
6679     c = fmt[++i] & 0xff;
6680     if(c == 0)
6681       break;
6682     switch(c){
6683     case 'd':
6684       printint(*argp++, 10, 1);
6685       break;
6686     case 'x':
6687     case 'p':
6688       printint(*argp++, 16, 0);
6689       break;
6690     case 's':
6691       if((s = (char*)*argp++) == 0)
6692         s = "(null)";
6693       for(; *s; s++)
6694         consputc(*s);
6695       break;
6696     case '%':
6697       consputc('%');
6698       break;
6699     default:
6700       // Print unknown % sequence to draw attention.
6701       consputc('%');
6702       consputc(c);
6703       break;
6704     }
6705   }
6706 
6707   if(locking)
6708     release(&cons.lock);
6709 }
6710 
6711 void
6712 panic(char *s)
6713 {
6714   int i;
6715   uint pcs[10];
6716 
6717   cli();
6718   cons.locking = 0;
6719   cprintf("cpu%d: panic: ", cpu->id);
6720   cprintf(s);
6721   cprintf("\n");
6722   getcallerpcs(&s, pcs);
6723   for(i=0; i<10; i++)
6724     cprintf(" %p", pcs[i]);
6725   panicked = 1; // freeze other CPU
6726   for(;;)
6727     ;
6728 }
6729 
6730 #define BACKSPACE 0x100
6731 #define CRTPORT 0x3d4
6732 static ushort *crt = (ushort*)0xb8000;  // CGA memory
6733 
6734 static void
6735 cgaputc(int c)
6736 {
6737   int pos;
6738 
6739   // Cursor position: col + 80*row.
6740   outb(CRTPORT, 14);
6741   pos = inb(CRTPORT+1) << 8;
6742   outb(CRTPORT, 15);
6743   pos |= inb(CRTPORT+1);
6744 
6745   if(c == '\n')
6746     pos += 80 - pos%80;
6747   else if(c == BACKSPACE){
6748     if(pos > 0) --pos;
6749   } else
6750     crt[pos++] = (c&0xff) | 0x0700;  // black on white
6751 
6752   if((pos/80) >= 24){  // Scroll up.
6753     memmove(crt, crt+80, sizeof(crt[0])*23*80);
6754     pos -= 80;
6755     memset(crt+pos, 0, sizeof(crt[0])*(24*80 - pos));
6756   }
6757 
6758   outb(CRTPORT, 14);
6759   outb(CRTPORT+1, pos>>8);
6760   outb(CRTPORT, 15);
6761   outb(CRTPORT+1, pos);
6762   crt[pos] = ' ' | 0x0700;
6763 }
6764 
6765 void
6766 consputc(int c)
6767 {
6768   if(panicked){
6769     cli();
6770     for(;;)
6771       ;
6772   }
6773 
6774   if(c == BACKSPACE){
6775     uartputc('\b'); uartputc(' '); uartputc('\b');
6776   } else
6777     uartputc(c);
6778   cgaputc(c);
6779 }
6780 
6781 
6782 struct {
6783   struct spinlock lock;
6784   char buf[INPUT_BUF];
6785   uint r;  // Read index
6786   uint w;  // Write index
6787   uint e;  // Edit index
6788 } input;
6789 
6790 #define C(x)  ((x)-'@')  // Control-x
6791 
6792 void
6793 consoleintr(int (*getc)(void))
6794 {
6795   int c;
6796   int i;
6797 
6798   acquire(&input.lock);
6799   while((c = getc()) >= 0){
6800     switch(c){
6801     case C('P'):  // Process listing.
6802       procdump();
6803       break;
6804     case C('U'):  // Kill line.
6805       while(input.e != input.w &&
6806             input.buf[(input.e-1) % INPUT_BUF] != '\n'){
6807         input.e--;
6808         consputc(BACKSPACE);
6809       }
6810       break;
6811     case C('I'): case 226: // up arrow
6812 	    if (numOfComm != 0)  {
6813 
6814 //cleaning the current line
6815 	    while(input.e != input.w &&
6816 			 input.buf[(input.e-1) % INPUT_BUF] != '\n'){
6817 		    input.e--;
6818 		    consputc(BACKSPACE);
6819 			 }
6820 
6821 
6822 //printing the last command
6823 
6824 	for (i=0; i<strlen(commands[arrowMarker]); i++){
6825 		input.buf[(input.e++ % INPUT_BUF)] = commands[arrowMarker][i];
6826 
6827 	}
6828 
6829 
6830 	    cprintf("%s",commands[arrowMarker]);
6831 
6832 //	    input.e = input.e + strlen(commands[arrowMarker]);
6833 
6834 //setting the arrowmarker to point at the right command for next time - cyclic
6835 	    if (arrowMarker == 0){
6836 		if (flag==1){
6837 			arrowMarker = 15;
6838 		}
6839 		else {
6840 			arrowMarker = numOfComm-1;
6841 		}
6842 	    }
6843 	    else //if historyMarker !=0
6844 	    {arrowMarker = arrowMarker - 1;}
6845 
6846 
6847 
6848 
6849 
6850 	    }
6851     break;
6852     case C('H'): case '\x7f':  // Backspace
6853       if(input.e != input.w){
6854         input.e--;
6855         consputc(BACKSPACE);
6856       }
6857       break;
6858 
6859 
6860 
6861     default:
6862       if(c != 0 && input.e-input.r < INPUT_BUF){
6863         c = (c == '\r') ? '\n' : c;
6864         input.buf[input.e++ % INPUT_BUF] = c;
6865         consputc(c);
6866         if(c == '\n' || c == C('D') || input.e == input.r+INPUT_BUF){
6867 
6868 //if we got \n that means that we got a complete command - now save it!
6869 	  strncpy(commands[historyMarker], &input.buf[input.w],input.e-input.w);
6870 
6871 	  commands[historyMarker][input.e-input.w-1] = 0;
6872 	  numOfComm = numOfComm + 1;
6873 
6874 //raise flag if the commands data structure is now full
6875 	  if (numOfComm == 16){
6876 		  flag = 1;
6877 	  }
6878 	  arrowMarker = historyMarker;
6879 
6880 //set historyMarker for next time - where in the DS to put it
6881 	  if (historyMarker ==15){
6882 		  historyMarker = 0;
6883 	  }
6884 	  else{
6885 		  historyMarker = historyMarker+1;
6886 	  }
6887 
6888 	  input.w = input.e;
6889 
6890           wakeup(&input.r);
6891         }
6892       }
6893       break;
6894     }
6895   }
6896   release(&input.lock);
6897 }
6898 
6899 
6900 int
6901 consoleread(struct inode *ip, char *dst, int n)
6902 {
6903 
6904   uint target;
6905   int c;
6906 
6907   iunlock(ip);
6908   target = n;
6909   acquire(&input.lock);
6910 
6911 
6912   while(n > 0){
6913     while(input.r == input.w){
6914       if(proc->killed){
6915         release(&input.lock);
6916         ilock(ip);
6917         return -1;
6918       }
6919       sleep(&input.r, &input.lock);
6920     }
6921     c = input.buf[input.r++ % INPUT_BUF];
6922     if(c == C('D')){  // EOF
6923       if(n < target){
6924         // Save ^D for next time, to make sure
6925         // caller gets a 0-byte result.
6926         input.r--;
6927       }
6928       break;
6929     }
6930     *dst++ = c;
6931 
6932     --n;
6933     if(c == '\n')
6934       break;
6935   }
6936 
6937 
6938 
6939   release(&input.lock);
6940   ilock(ip);
6941 
6942   return target - n;
6943 }
6944 
6945 
6946 
6947 
6948 
6949 
6950 int
6951 consolewrite(struct inode *ip, char *buf, int n)
6952 {
6953   int i;
6954 
6955   iunlock(ip);
6956   acquire(&cons.lock);
6957   for(i = 0; i < n; i++)
6958     consputc(buf[i] & 0xff);
6959   release(&cons.lock);
6960   ilock(ip);
6961 
6962   return n;
6963 }
6964 
6965 void
6966 consoleinit(void)
6967 {
6968   initlock(&cons.lock, "console");
6969   initlock(&input.lock, "input");
6970 
6971   devsw[CONSOLE].write = consolewrite;
6972   devsw[CONSOLE].read = consoleread;
6973   cons.locking = 1;
6974 
6975   picenable(IRQ_KBD);
6976   ioapicenable(IRQ_KBD, 0);
6977 }
6978 
6979 
6980 
6981 
6982 
6983 
6984 
6985 
6986 
6987 
6988 
6989 
6990 
6991 
6992 
6993 
6994 
6995 
6996 
6997 
6998 
6999 
